from flask import Blueprint, request, jsonify, current_app
from flask_login import login_required, current_user
# 移除JWT导入，使用Flask-Login会话认证
from models import Post, Category, Tag, PostTag, Comment
from extensions import db
from sqlalchemy import desc, or_
from datetime import datetime
import logging
from utils.html_generator import html_generator

logger = logging.getLogger('Personal_Blog_System')

# 辅助函数
def to_bool(value):
    """将各种值转换为布尔值"""
    if isinstance(value, bool):
        return value
    if isinstance(value, str):
        return value.lower() in ('true', '1', 'yes', 'on')
    return bool(value)

# 创建文章API蓝图
post_api = Blueprint('post_api', __name__, url_prefix='/api/posts')

@post_api.route('/', methods=['GET'])
def get_posts():
    """获取文章列表"""
    try:
        page = request.args.get('page', 1, type=int)
        per_page = request.args.get('per_page', 10, type=int)
        status = request.args.get('status', '')
        category_id = request.args.get('category', type=int)
        tag_id = request.args.get('tag_id', type=int)
        search = request.args.get('search', '')
        
        # 构建查询
        query = Post.query
        
        if status:
            query = query.filter_by(status=status)
        
        if category_id:
            query = query.filter_by(category_id=category_id)
        
        if tag_id:
            query = query.filter(Post.tags.any(Tag.id == tag_id))
        
        if search:
            query = query.filter(
                or_(
                    Post.title.contains(search),
                    Post.content.contains(search),
                    Post.excerpt.contains(search)
                )
            )
        
        # 排序和分页
        posts = query.order_by(desc(Post.created_at)).paginate(
            page=page, per_page=per_page, error_out=False
        )
        
        # 构建响应数据
        posts_data = []
        for post in posts.items:
            posts_data.append({
                'id': post.id,
                'title': post.title,
                'excerpt': post.excerpt,
                'cover_image': post.cover_image,
                'author': {
                    'id': post.author.id,
                    'username': post.author.username,
                    'name': post.author.name,
                    'avatar': post.author.avatar
                },
                'category': {
                    'id': post.category.id if post.category else None,
                    'name': post.category.name if post.category else None,
                    'color': post.category.color if post.category else None
                } if post.category else None,
                'tags': [{'id': tag.id, 'name': tag.name} for tag in post.tags],
                'status': post.status,
                'is_featured': post.is_featured,
                'view_count': post.view_count,
                'like_count': post.like_count,
                'comment_count': post.comment_count,
                'html_path': post.html_path,
                'published_at': post.published_at.isoformat() if post.published_at else None,
                'created_at': post.created_at.isoformat(),
                'updated_at': post.updated_at.isoformat()
            })
        
        return jsonify({
            'success': True,
            'data': {
                'posts': posts_data,
                'pagination': {
                    'page': posts.page,
                    'pages': posts.pages,
                    'per_page': posts.per_page,
                    'total': posts.total,
                    'has_next': posts.has_next,
                    'has_prev': posts.has_prev
                }
            }
        })
        
    except Exception as e:
        logger.error(f"获取文章列表失败: {str(e)}")
        return jsonify({'success': False, 'message': '获取文章列表失败'}), 500

@post_api.route('/<int:post_id>', methods=['GET'])
def get_post(post_id):
    """获取单篇文章"""
    try:
        post = Post.query.get_or_404(post_id)
        
        # 如果是草稿且不是作者本人，返回404
        if post.status == 'draft' and (not current_user.is_authenticated or post.author_id != current_user.id):
            return jsonify({'success': False, 'message': '文章不存在'}), 404
        
        post_data = {
        'id': post.id,
        'title': post.title,
        'content': post.content,
            'excerpt': post.excerpt,
            'cover_image': post.cover_image,
            'author': {
                'id': post.author.id,
                'username': post.author.username,
                'name': post.author.name,
                'avatar': post.author.avatar,
                'bio': post.author.bio
            },
            'category': {
                'id': post.category.id if post.category else None,
                'name': post.category.name if post.category else None
            } if post.category else None,
            'tags': [{'id': tag.id, 'name': tag.name} for tag in post.tags],
            'status': post.status,
            'is_featured': post.is_featured,
            'allow_comments': post.allow_comments,
            'view_count': post.view_count,
            'like_count': post.like_count,
            'comment_count': post.comment_count,
            'published_at': post.published_at.isoformat() if post.published_at else None,
            'created_at': post.created_at.isoformat(),
            'updated_at': post.updated_at.isoformat()
        }
        
        return jsonify({'success': True, 'data': post_data})
        
    except Exception as e:
        logger.error(f"获取文章失败: {str(e)}")
        return jsonify({'success': False, 'message': '获取文章失败'}), 500

@post_api.route('/', methods=['POST'])
@login_required
def create_post():
    """创建文章"""
    try:
        data = request.get_json()
        user_id = current_user.id
        
        # 验证必填字段
        required_fields = ['title', 'content']
        for field in required_fields:
            if not data.get(field) or (isinstance(data.get(field), str) and not data.get(field).strip()):
                logger.error(f"缺少必填字段: {field}")
                return jsonify({'success': False, 'message': f'{field}是必填字段'}), 400
        
        # 验证标题长度
        if len(data['title'].strip()) > 200:
            return jsonify({'success': False, 'message': '标题长度不能超过200个字符'}), 400
        
        # 验证内容长度
        if len(data['content'].strip()) < 10:
            return jsonify({'success': False, 'message': '文章内容至少需要10个字符'}), 400
        
        # 验证分类ID（如果提供）
        if data.get('category_id'):
            try:
                category_id = int(data['category_id'])
                category = Category.query.get(category_id)
                if not category:
                    return jsonify({'success': False, 'message': '选择的分类不存在'}), 400
            except (ValueError, TypeError):
                return jsonify({'success': False, 'message': '分类ID格式错误'}), 400
        
        # 创建文章
        post = Post(
            title=data['title'],
            content=data['content'],
            excerpt=data.get('excerpt', ''),
            cover_image=data.get('cover_image'),
            author_id=user_id,
            category_id=data.get('category_id'),
            status=data.get('status', 'draft'),
            is_featured=to_bool(data.get('is_featured', False)),
            allow_comments=to_bool(data.get('allow_comments', True))
        )
        
        # 如果是发布状态，设置发布时间
        if post.status == 'published':
            post.published_at = datetime.utcnow()
        
        db.session.add(post)
        db.session.flush()  # 获取post.id
        
        # 处理标签
        if data.get('tags'):
            # 去重标签
            unique_tags = []
            seen_tags = set()
            
            for tag_data in data['tags']:
                if isinstance(tag_data, dict) and 'id' in tag_data:
                    tag_id = tag_data['id']
                    if tag_id not in seen_tags:
                        unique_tags.append(tag_data)
                        seen_tags.add(tag_id)
                elif isinstance(tag_data, str) and tag_data.strip():
                    tag_name = tag_data.strip()
                    if tag_name and tag_name not in seen_tags:
                        unique_tags.append(tag_name)
                        seen_tags.add(tag_name)
            
            for tag_data in unique_tags:
                if isinstance(tag_data, dict) and 'id' in tag_data:
                    tag = Tag.query.get(tag_data['id'])
                elif isinstance(tag_data, str) and tag_data.strip():
                    # 过滤空标签名
                    tag_name = tag_data.strip()
                    if tag_name:
                        tag = Tag.query.filter_by(name=tag_name).first()
                        if not tag:
                            # 创建新标签
                            tag = Tag(name=tag_name)
                            db.session.add(tag)
                            db.session.flush()
                    else:
                        tag = None
                else:
                    tag = None
                
                if tag:
                    # 检查是否已存在关联
                    existing_post_tag = PostTag.query.filter_by(post_id=post.id, tag_id=tag.id).first()
                    if not existing_post_tag:
                        post_tag = PostTag(post_id=post.id, tag_id=tag.id)
                        db.session.add(post_tag)
        
        db.session.commit()
        
        # 如果是发布状态，生成静态HTML
        if post.status == 'published':
            try:
                html_path = html_generator.generate_post_html(post)
                post.html_path = html_path
                db.session.commit()
                logger.info(f"文章 {post.id} 静态HTML生成成功: {html_path}")
            except Exception as e:
                logger.error(f"生成静态HTML失败: {str(e)}")
                # 不阻止文章创建，只记录错误
        
        return jsonify({
            'success': True,
            'message': '文章创建成功',
            'data': {'id': post.id, 'html_path': post.html_path}
        }), 201
        
    except Exception as e:
        logger.error(f"创建文章失败: {str(e)}")
        db.session.rollback()
        return jsonify({'success': False, 'message': '创建文章失败'}), 500

@post_api.route('/<int:post_id>', methods=['PUT'])
@login_required
def update_post(post_id):
    """更新文章"""
    try:
        post = Post.query.get_or_404(post_id)
        user_id = current_user.id
        
        # 检查权限
        if post.author_id != user_id and current_user.role != 'admin':
            return jsonify({'success': False, 'message': '没有权限修改此文章'}), 403
        
        data = request.get_json()
        
        # 验证更新数据
        if 'title' in data:
            if not data['title'] or not data['title'].strip():
                return jsonify({'success': False, 'message': '标题不能为空'}), 400
            if len(data['title'].strip()) > 200:
                return jsonify({'success': False, 'message': '标题长度不能超过200个字符'}), 400
            post.title = data['title']
        
        if 'content' in data:
            if not data['content'] or not data['content'].strip():
                return jsonify({'success': False, 'message': '内容不能为空'}), 400
            if len(data['content'].strip()) < 10:
                return jsonify({'success': False, 'message': '文章内容至少需要10个字符'}), 400
            post.content = data['content']
        
        if 'excerpt' in data:
            post.excerpt = data['excerpt']
        
        if 'cover_image' in data:
            post.cover_image = data['cover_image']
        
        if 'category_id' in data:
            post.category_id = data['category_id']
        
        if 'status' in data:
            post.status = data['status']
            # 如果状态改为published且之前未发布，设置发布时间
            if data['status'] == 'published' and not post.published_at:
                post.published_at = datetime.utcnow()
        
        if 'is_featured' in data:
            post.is_featured = to_bool(data['is_featured'])
        
        if 'allow_comments' in data:
            post.allow_comments = to_bool(data['allow_comments'])
        
        # 处理标签
        if 'tags' in data:
            # 删除现有标签关联
            PostTag.query.filter_by(post_id=post.id).delete()
            
            # 添加新标签
            # 去重标签
            unique_tags = []
            seen_tags = set()
            
            for tag_data in data['tags']:
                if isinstance(tag_data, dict) and 'id' in tag_data:
                    tag_id = tag_data['id']
                    if tag_id not in seen_tags:
                        unique_tags.append(tag_data)
                        seen_tags.add(tag_id)
                elif isinstance(tag_data, str) and tag_data.strip():
                    tag_name = tag_data.strip()
                    if tag_name and tag_name not in seen_tags:
                        unique_tags.append(tag_name)
                        seen_tags.add(tag_name)
            
            for tag_data in unique_tags:
                if isinstance(tag_data, dict) and 'id' in tag_data:
                    tag = Tag.query.get(tag_data['id'])
                elif isinstance(tag_data, str) and tag_data.strip():
                    # 过滤空标签名
                    tag_name = tag_data.strip()
                    if tag_name:
                        tag = Tag.query.filter_by(name=tag_name).first()
                        if not tag:
                            tag = Tag(name=tag_name)
                            db.session.add(tag)
                            db.session.flush()
                    else:
                        tag = None
                else:
                    tag = None
                
                if tag:
                    # 检查是否已存在关联
                    existing_post_tag = PostTag.query.filter_by(post_id=post.id, tag_id=tag.id).first()
                    if not existing_post_tag:
                        post_tag = PostTag(post_id=post.id, tag_id=tag.id)
                        db.session.add(post_tag)
        
        db.session.commit()
        
        # 如果是发布状态，生成或更新静态HTML
        if post.status == 'published':
            try:
                html_path = html_generator.update_post_html(post)
                logger.info(f"文章 {post.id} 静态HTML更新成功: {html_path}")
            except Exception as e:
                logger.error(f"更新静态HTML失败: {str(e)}")
                # 不阻止文章更新，只记录错误
        elif post.html_path:
            # 如果文章状态不是发布，删除静态HTML
            try:
                html_generator.delete_post_html(post.html_path)
                post.html_path = None
                db.session.commit()
                logger.info(f"文章 {post.id} 静态HTML已删除")
            except Exception as e:
                logger.error(f"删除静态HTML失败: {str(e)}")
        
        return jsonify({'success': True, 'message': '文章更新成功'})
        
    except Exception as e:
        logger.error(f"更新文章失败: {str(e)}")
        db.session.rollback()
        return jsonify({'success': False, 'message': '更新文章失败'}), 500

@post_api.route('/<int:post_id>', methods=['DELETE'])
@login_required
def delete_post(post_id):
    """删除文章"""
    try:
        post = Post.query.get_or_404(post_id)
        user_id = current_user.id
        
        # 检查权限
        if post.author_id != user_id and current_user.role != 'admin':
            return jsonify({'success': False, 'message': '没有权限删除此文章'}), 403
        
        # 删除静态HTML文件
        if post.html_path:
            try:
                html_generator.delete_post_html(post.html_path)
                logger.info(f"文章 {post.id} 静态HTML已删除")
            except Exception as e:
                logger.error(f"删除静态HTML失败: {str(e)}")
        
        # 删除文章（级联删除评论）
        db.session.delete(post)
        db.session.commit()
        
        return jsonify({'success': True, 'message': '文章删除成功'})
        
    except Exception as e:
        logger.error(f"删除文章失败: {str(e)}")
        db.session.rollback()
        return jsonify({'success': False, 'message': '删除文章失败'}), 500

@post_api.route('/<int:post_id>/like', methods=['POST'])
def like_post(post_id):
    """点赞文章"""
    try:
        post = Post.query.get_or_404(post_id)
        post.like_count += 1
        db.session.commit()
        
        return jsonify({'success': True, 'message': '点赞成功', 'like_count': post.like_count})
        
    except Exception as e:
        logger.error(f"点赞失败: {str(e)}")
        db.session.rollback()
        return jsonify({'success': False, 'message': '点赞失败'}), 500

@post_api.route('/<int:post_id>/stats')
def get_post_stats(post_id):
    """获取文章统计数据"""
    try:
        post = Post.query.get_or_404(post_id)
        
        # 增加阅读数
        if post.view_count is None:
            post.view_count = 1
        else:
            post.view_count += 1
        db.session.commit()
        
        return jsonify({
            'success': True,
            'view_count': post.view_count or 0,
            'like_count': post.like_count or 0,
            'comment_count': post.comment_count or 0
        })
        
    except Exception as e:
        logger.error(f"获取统计数据失败: {str(e)}")
        return jsonify({'success': False, 'message': '获取统计数据失败'}), 500

